package org.meichao.config.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 系统日志切面处理
 * @Aspect 把当前类 标识为一个切面供容器读取
 *  -@Before 前置通知，目标方法执行之前执行以下方法体内容
 *  -@AfterReturning 目标方法正常执行完毕后执行以下方法体内容
 */
@Aspect
@Component
public class LoggerAop {

    private static Logger logger = LoggerFactory.getLogger(LoggerAop.class);

    /**
     * 匹配org.meichao.*.controller包下所有类的,所有方法的执行作为切入点
     * 第一个..表示controller包及其子包,之后第一个*表示所有类,第二个*表示所有方法,最后..表示方法的任意参数
     * @Pointcut 注入Advice位置集合，即切入点
     */
    @Pointcut("execution(public * org.meichao.*.controller..*.*(..))")
    public void cutPoint(){
    }

    @Before("cutPoint()")
    public void doBefore(JoinPoint joinPoint) throws Throwable{
        //接受到请求
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //记录请求内容
        logger.info("url: {}", request.getRequestURL().toString());
        logger.info("ip: {}", request.getRemoteAddr());
        logger.info("requestMethod: {}", request.getMethod());
        logger.info("classMethod: {}", joinPoint.getSignature().getDeclaringTypeName() +
                "." + joinPoint.getSignature().getName());
        logger.info("args: {}", Arrays.toString(joinPoint.getArgs()));
    }

    /**
     *指定了returning属性值为obj，
     * 表明允许在Advice方法（doAfterReturning()方法）中定义名为obj的形参，
     * 程序可通过obj形参来访问目标方法的返回值
     */
    @AfterReturning(returning = "obj", pointcut = "cutPoint()")
    public void doAfterReturning(Object obj) throws Throwable {
        //处理完请求,返回内容
        logger.info("response:" + obj);
    }
}
